package instant.monitor.test;

import com.ilikesoup.instant.monitor.core.MethodNameFilter;
import com.ilikesoup.instant.monitor.sample.BeanMonitorBuilder;
import com.ilikesoup.instant.monitor.sample.ChangeEventTriggerWrapper;
import com.ilikesoup.instant.monitor.sample.MonitorBeanFactory;
import com.ilikesoup.instant.monitor.sample.trigger.BeanWriteTrigger;
import com.ilikesoup.instant.monitor.sample.trigger.MethodWriteTrigger;
import lombok.Data;
import net.sf.cglib.beans.BeanCopier;
import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

public class BeanMonitorTestCase {

    @Test
    public void test() {
        BeanMonitorBuilder beanMonitorBuilder = new BeanMonitorBuilder().addListener(new BeanWriteTrigger.BeanWriteListener())
                .addMethodTrigger(MethodNameFilter.WRITE_METHOD_FILTER, new BeanWriteTrigger());
        Model model = beanMonitorBuilder.newMonitoredInstance(Model.class);
        model.setA("abc");
        model.setB(1111);
        model.setC((byte) 1);
        model.setD(new Date());

        model.setA("ABC");
        model.setB(1112);
        model.setC((byte) 22);
        model.setD(new Date());
    }

    @Test
    public void testCollection() {
        BeanMonitorBuilder beanMonitorBuilder = new BeanMonitorBuilder().addListener(new MethodWriteTrigger.MethodWriteListener())
                .addMethodTrigger(MethodNameFilter.in("add", "remove", "addAll", "removeAll"), new MethodWriteTrigger());
        List<String> modelList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            modelList.add(String.valueOf(i));
        }
        List<String> monitor = beanMonitorBuilder.monitor(modelList, Collection::addAll);
        monitor.add("abc");
        monitor.remove("1");
        monitor.removeAll(Arrays.asList("2", "3", "4"));
        monitor.add(3, "xxx");

        Iterator<String> iterator = monitor.iterator();
        while(iterator.hasNext()) {
            String it = iterator.next();
            if(it.matches("\\d")) {
                iterator.remove();
            }
        }
    }

    @Test
    public void testModelCollection() {
        BiConsumer beanCopierConsumer = (proxy, target) -> {
                BeanCopier beanCopier = BeanCopier.create(target.getClass(), proxy.getClass(), false);
                beanCopier.copy(target, proxy, null);
            };

        BeanMonitorBuilder modelMonitorBuilder = new BeanMonitorBuilder().addListener(new BeanWriteTrigger.BeanWriteListener())
                .addMethodTrigger(MethodNameFilter.WRITE_METHOD_FILTER, new BeanWriteTrigger());
        BeanMonitorBuilder beanMonitorBuilder = new BeanMonitorBuilder().addListener(new MethodWriteTrigger.MethodWriteListener())
                .addMethodTrigger(MethodNameFilter.in("add", "remove", "addAll", "removeAll"),
                        new ChangeEventTriggerWrapper(new MethodWriteTrigger()).monitorArgs(
                                source -> {
                                    MonitorBeanFactory monitorBeanFactory = new MonitorBeanFactory(modelMonitorBuilder, beanCopierConsumer);
                                    if(source instanceof Collection) {
                                        Collection c = (Collection) source;
                                        return c.stream().map(monitorBeanFactory::wrap).collect(Collectors.toList());
                                    }
                                    return monitorBeanFactory.wrap(source);
                                }));
        List<Model> modelList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            modelList.add(new Model());
        }
        List<Model> monitor = beanMonitorBuilder.monitor(modelList, Collection::addAll);
        monitor.forEach(model -> model.setA("abc"));
    }




    @Data
    public static class Model {
        private String a;
        private Integer b;
        private byte c;
        private Date d;
    }


}
